package contegor.scire.core.queries;

import com.sun.corba.se.spi.ior.Identifiable;

import contegor.scire.core.Connectable;
import contegor.scire.core.Id;
import contegor.scire.core.Link;

/**
 * Abstract base {@link Condition} for those that filters {@link Connectable}s and let them pass
 * depending if the {@link Link} between it and the target {@link Id} fulfills {@link #getLinkFulfillsCondition(Connectable)}.
 * Also allows nesting other {@link Condition}s that are applied to the {@link Link} between
 * the {@link Connectable} and the {@link Identifiable}, if such {@link Link} exists.
 *
 * @author  Héctor Cirbián Pousa
 */
public abstract class TargetNestCondition<C extends Connectable> extends Condition<C> {
  private static final long serialVersionUID = 1219309671932080764L;

  protected Id              target;
  protected Condition<Link> nested;

  /** 
   * Creates a {@link Condition} that filters {@link Connectable}s and lets them pass if they and the
   * target {@link Id} fulfill the {@link #getLinkFulfillsCondition(Connectable)}.
   */
  protected TargetNestCondition(Id target) {
    super();
    this.target = target;
  }

  /**
   * Creates a {@link Condition} that filters {@link Connectable}s and lets them pass if they and the
   * target {@link Id} fulfill the {@link #getLinkFulfillsCondition(Connectable)}.
   * The {@link Link} in between must also fulfill with the nested {@link Condition}.
   * The {@link Condition#eval(Connectable)} method will do a logic <code>and</code> between the two checks. It is granted that the main condition will
   * be evaluated first and, if it is true, the nested will be evaluated.
   */
  protected TargetNestCondition(Id target, Condition<Link> nested) {
    super();
    this.target = target;
    this.nested = nested;
  }

  protected abstract Link getLinkFulfillsCondition(C source);

  @Override
  public boolean eval(C source) {
    Link link = getLinkFulfillsCondition(source);
    if (link != null) {
      if (nested == null)
        return true;
      return nested.eval(link);
    }
    else
      return false;
  }
}